﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using JasLib.Interop;

namespace JasLib.Interop.Win32
{
    public static class NTDLL
    {
        [Obsolete]
        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "NtOpenDirectoryObject", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS NtOpenDirectoryObject(
            [Out] out HANDLE DirectoryHandle,
            [In] DirectoryAccessRights DesiredAccess,
            [In] ref OBJECT_ATTRIBUTES ObjectAttributes);

        [Obsolete]
        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "NtQueryDirectoryObject", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS NtQueryDirectoryObject(
            [In] HANDLE DirectoryHandle,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] Buffer,
            [In] uint Length,
            [In] BOOLEAN ReturnSingleEntry,
            [In] BOOLEAN RestartScan,
            [In, Out] ref uint Context,
            [Out] out uint ReturnLength);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "NtQueryInformationProcess", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS NtQueryInformationProcess(
            [In] HANDLE ProcessHandle,
            [In] PROCESSINFOCLASS ProcessInformationClass,
            [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] ProcessInformation,
            [In] int ProcessInformationLength,
            [Out] out int ReturnLength);

        public static void NtQueryInformationProcess(
            HANDLE ProcessHandle,
            out PROCESS_BASIC_INFORMATION ProcessInformation)
        {
            int iReturnLength;
            ProcessInformation = new PROCESS_BASIC_INFORMATION();
            byte[] buffer = ProcessInformation.GetBytes();
            NTSTATUS eReturnValue = NtQueryInformationProcess(ProcessHandle, PROCESSINFOCLASS.ProcessBasicInformation, buffer, buffer.Length, out iReturnLength);
            eReturnValue.TryThrowNtException();
            ProcessInformation = buffer.FromBytes<PROCESS_BASIC_INFORMATION>();
            return;
        }

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "NtQueryObject", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS NtQueryObject(
            [In] HANDLE Handle,
            [In] OBJECT_INFORMATION_CLASS ObjectInformationClass,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] ObjectInformation,
            [In] uint ObjectInformationLength,
            [Out] out uint ReturnLength);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "NtQueryObject", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS NtQueryObject(
            HANDLE Handle,
            OBJECT_INFORMATION_CLASS ObjectInformationClass,
            ref OBJECT_NAME_INFORMATION ObjectInformation,
            uint ObjectInformationLength,
            out uint ReturnLength);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "NtQueryObject", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS NtQueryObject(
            HANDLE Handle,
            OBJECT_INFORMATION_CLASS ObjectInformationClass,
            ref PUBLIC_OBJECT_TYPE_INFORMATION ObjectInformation,
            uint ObjectInformationLength,
            out uint ReturnLength);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "NtQueryObject", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS NtQueryObject(
            HANDLE Handle,
            OBJECT_INFORMATION_CLASS ObjectInformationClass,
            ref PUBLIC_OBJECT_BASIC_INFORMATION ObjectInformation,
            uint ObjectInformationLength,
            out uint ReturnLength);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "RtlFreeUnicodeString", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern void RtlFreeUnicodeString(ref UNICODE_STRING UnicodeString);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "RtlInitUnicodeString", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern void RtlInitUnicodeString(ref UNICODE_STRING DestinationString, string SourceString);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "RtlIpv4AddressToStringExW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS RtlIpv4AddressToStringEx(
            [In] ref IN_ADDR Address,
            [In] ushort Port,
            [Out] StringBuilder AddressString,
            [In, Out] ref uint AddressStringLength);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "RtlIpv4StringToAddressExW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS RtlIpv4StringToAddressEx(
            [In] string AddressString,
            [In, MarshalAs(UnmanagedType.Bool)] bool Strict,
            [Out] out IN_ADDR Address,
            [Out] out ushort Port);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "RtlIpv6AddressToStringExW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS RtlIpv6AddressToStringEx(
            [In] ref IN6_ADDR Address,
            [In] uint ScopeId,
            [In] ushort Port,
            [Out] StringBuilder AddressString,
            [In, Out] ref uint AddressStringLength);

        [DllImport(Constants.ModuleNames.NTDLL, EntryPoint = "RtlIpv6StringToAddressExW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern NTSTATUS RtlIpv6StringToAddressEx(
            [In] string AddressString,
            [Out] out IN6_ADDR Address,
            [Out] out uint ScopeId,
            [Out] out ushort Port);
    }
}